package com.huiminpay.transaction.service;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huiminpay.common.cache.Cache;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.common.cache.util.RedisUtil;
import com.huiminpay.common.cache.util.StringUtil;
import com.huiminpay.transaction.api.PayChannelService;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;
import com.huiminpay.transaction.convert.PayChannelConvert;
import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Service  //dubbo注解
public class PayChannelServiceImpl implements PayChannelService
{

    @Autowired
    PlatformChannelMapper platformChannelMapper;
    @Autowired
    AppPlatformChannelMapper appPlatformChannelMapper;
    @Autowired
    PayChannelParamMapper payChannelParamMapper;
    @Autowired
    Cache redisCache;


    /**
     * 查询服务类型
     *
     * @return 服务类型列表
     * @throws BusinessException
     */
    @Override
    public List<PlatformChannelDTO> queryPlatformChannel() throws BusinessException {
        List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);
        List<PlatformChannelDTO> platformChannelDTOS = PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);

        return platformChannelDTOS;
    }

    /**
     * 给应用绑定服务类型
     *
     * @param appId               应用Id
     * @param plarformChannelCode 服务类型code
     * @throws BusinessException
     */
    @Override
    public void bindPlatformChannelForApp(String appId, String plarformChannelCode) throws BusinessException {
        //校验
        if (StringUtil.isBlank(appId) || StringUtil.isBlank(plarformChannelCode)) {
            throw new BusinessException(CommonErrorCode.E_110006);
        }
        // 看该应用和服务类型是否已绑定,未绑定才绑定
        Integer count = appPlatformChannelMapper.selectCount(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, plarformChannelCode));

        if (count <= 0) {
            //绑定
            AppPlatformChannel appPlatformChannel = new AppPlatformChannel();
            appPlatformChannel.setAppId(appId);
            appPlatformChannel.setPlatformChannel(plarformChannelCode);
            appPlatformChannelMapper.insert(appPlatformChannel);
        }
    }

    /**
     * 查询应用和服务类型的绑定状态
     *
     * @param appId               应用Id
     * @param plarformChannelCode 服务类型code
     * @return 1:已绑定  2:未绑定
     * @throws BusinessException
     */
    @Override
    public int queryAppBindPlatformChannel(String appId, String plarformChannelCode) throws BusinessException {
        Integer count = appPlatformChannelMapper.selectCount(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, plarformChannelCode));
        if (count > 0) {
            return 1;
        }

        return 0;
    }

    /**
     * 根据服务类型,查询支付渠道
     *
     * @param plarformChannelCode 服务类型code
     * @return 支付渠道列表
     * @throws BusinessException
     */
    @Override
    public List<PayChannelDTO> queryPayChannelByPlatformChannel(String plarformChannelCode) throws BusinessException {
        List<PayChannel> payChannelList = platformChannelMapper.selectPayChannelByPlatformChannel(plarformChannelCode);
        List<PayChannelDTO> payChannelDTOList = PayChannelConvert.INSTANCE.entityListToDtoList(payChannelList);
        return payChannelDTOList;
    }

    /**
     * 保存支付渠道参数
     *
     * @param paramDTO 商户Id  应用Id  服务类型  支付渠道code
     * @throws BusinessException
     */
    @Override
    public void savePayChannelParam(PayChannelParamDTO paramDTO) throws BusinessException {

        if(paramDTO == null
                || StringUtils.isBlank(paramDTO.getAppId())
                || StringUtils.isBlank(paramDTO.getPlatformChannelCode())
                || StringUtils.isBlank(paramDTO.getPayChannel())){
            throw new BusinessException(CommonErrorCode.E_300009);
        }

        //先看某支付渠道是否被配置   如果已配置则修改  没有支配则新增

        //根据应用和服务类型查询绑定关系的Id
        Long appPlatformChannelID = selectIdByAppPlatformChannel(paramDTO.getAppId(), paramDTO.getPlatformChannelCode());

        if (appPlatformChannelID == null) {
            throw new BusinessException(CommonErrorCode.E_300010);
        }
        //查询支付参数
        PayChannelParam payChannelParam = payChannelParamMapper.selectOne(new LambdaQueryWrapper<PayChannelParam>()
                .eq(PayChannelParam::getAppPlatformChannelId, appPlatformChannelID)
                .eq(PayChannelParam::getPayChannel, paramDTO.getPayChannel()));

        //如果有就更新
        if (payChannelParam!=null) {
            payChannelParam.setChannelName(paramDTO.getChannelName());
            payChannelParam.setParam(paramDTO.getParam());
            payChannelParamMapper.updateById(payChannelParam);
         }else {
            //没有则新增
           /*方法一

            payChannelParam.setChannelName(paramDTO.getChannelName());
            payChannelParam.setMerchantId(paramDTO.getMerchantId());
            payChannelParam.setAppPlatformChannelId(appPlatformChannelID);
            payChannelParam.setPayChannel(paramDTO.getPayChannel());
            payChannelParam.setParam(paramDTO.getParam());

            payChannelParamMapper.insert(payChannelParam);
           */

            //方法二
            PayChannelParam channelParam = PayChannelParamConvert.INSTANCE.dto2entity(paramDTO);
            channelParam.setAppPlatformChannelId(appPlatformChannelID);
            payChannelParamMapper.insert(channelParam);

            //向缓存中存入数据
            updateCache(paramDTO.getAppId(),paramDTO.getPlatformChannelCode());
        }
    }

    /**
     * 更新缓存
     * @param appId  应用ID
     * @param platformChannelCode  服务类型code
     */
    private void updateCache(String appId, String platformChannelCode){
        //组装key
        String key = RedisUtil.keyBuilder(appId, platformChannelCode);
        if (redisCache.exists(key)) {
            //如果存在则删除
            redisCache.del(key);
        }
        //存value  参数支付列表
        List<PayChannelParamDTO> payChannelParamDTOS = queryPayChannelParamByAppAndPlatform(appId, platformChannelCode);

        //序列化为json存入
        String params_json = JSON.toJSONString(payChannelParamDTOS);

        //存入
        redisCache.set(key,params_json);

    }

    /**
     * 根据应用服务和类型查询支付参数
     * @param appId               应用Id
     * @param platformChannelCode 服务类型Code
     * @return 支付参数列表
     * @throws BusinessException
     */
    @Override
    public List<PayChannelParamDTO> queryPayChannelParamByAppAndPlatform(String appId, String platformChannelCode) throws BusinessException {

        //先从缓存中查找数据
        //组装key
        String key = RedisUtil.keyBuilder(appId, platformChannelCode);

        String params_json = redisCache.get(key);
        if (!StringUtil.isBlank(params_json)) {
            //将json转换为对象
            List<PayChannelParamDTO> payChannelParamDTOS1 = JSON.parseArray(params_json, PayChannelParamDTO.class);
            return payChannelParamDTOS1;
        }

        //缓存中没有再去查找数据库
        //根据应用和服务类型查询绑定关系的Id
        Long appPlatformChannelId = selectIdByAppPlatformChannel(appId, platformChannelCode);
        if (appPlatformChannelId == null) {
            throw new BusinessException(CommonErrorCode.E_300010);
        }
        List<PayChannelParam> payChannelParamList = payChannelParamMapper.selectList(new LambdaQueryWrapper<PayChannelParam>()
                .eq(PayChannelParam::getAppPlatformChannelId, appPlatformChannelId));
        //  查完再向缓存中存一份
//        updateCache(appId,platformChannelCode);
        redisCache.set(key,JSON.toJSONString(payChannelParamList));

        List<PayChannelParamDTO> payChannelParamDTOS = PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParamList);
        return payChannelParamDTOS;
    }

    /**
     * 根据应用,服务类型,支付渠道查询支付参数
     *
     * @param appId               应用Id
     * @param platformChannelCode 服务类型Code
     * @param payChannelCode      支付渠道Code
     * @return 该支付渠道的支付参数
     * @throws BusinessException
     */
    @Override
    public PayChannelParamDTO queryParamByAppPlatformAndPayChannel(String appId, String platformChannelCode, String payChannelCode) throws BusinessException {
        List<PayChannelParamDTO> payChannelParamDTOS = queryPayChannelParamByAppAndPlatform(appId, platformChannelCode);
        if (payChannelParamDTOS != null) {
            for (PayChannelParamDTO payChannelParamDTO : payChannelParamDTOS) {
                if (payChannelCode.equals(payChannelParamDTO.getPayChannel())) {
                    return payChannelParamDTO;
                }
            }
        }
        return null;
    }

    /**
     * 根据应用和服务类型查询绑定关系的Id
     * @param appId  应用Id
     * @param platformChannelCode  服务类型code
     * @return   绑定关系ID
     */
    private Long selectIdByAppPlatformChannel(String appId,String platformChannelCode){
        AppPlatformChannel appPlatformChannel = appPlatformChannelMapper.selectOne(new LambdaQueryWrapper<AppPlatformChannel>()
                .eq(AppPlatformChannel::getAppId, appId)
                .eq(AppPlatformChannel::getPlatformChannel, platformChannelCode));
        if (appPlatformChannel != null){
            Long id = appPlatformChannel.getId();
            return id;
        }
        return null;
    }





}
